package com.company;

import java.util.*;
import java.util.stream.Collectors;

public class ZhengShangYou{
    // 扑克牌花色
    private static final String[] SUITS = {"♥", "♦", "♠", "♣"};
    // 扑克牌点数
    private static final String[] RANKS = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
    // 牌型定义
    private static final int SINGLE = 1;          // 单张
    private static final int PAIR = 2;            // 对子
    private static final int TRIPLE = 3;          // 三张
    private static final int STRAIGHT = 4;        // 顺子
    private static final int STRAIGHT_PAIR = 5;   // 连对
    private static final int AIRPLANE = 6;        // 飞机
    private static final int BOMB = 7;            // 炸弹
    private static final int KING_BOMB = 8;       // 王炸

    private List<Card> deck;                      // 牌堆
    private List<Player> players;                // 玩家列表
    private List<Card> lastPlayedCards;          // 上一手牌
    private int currentPlayerIndex;              // 当前玩家索引

    public static void main(String[] args) {
        ZhengShangYou game = new ZhengShangYou();
        game.initializeGame();
        game.play();
    }

    // 初始化游戏
    private void initializeGame() {
        // 创建一副牌
        deck = new ArrayList<>();
        for (String suit : SUITS) {
            for (String rank : RANKS) {
                deck.add(new Card(suit, rank));
            }
        }
        // 添加大小王
        deck.add(new Card("", "小王"));
        deck.add(new Card("", "大王"));

        // 洗牌
        Collections.shuffle(deck);

        // 创建玩家
        players = new ArrayList<>();
        players.add(new HumanPlayer("你"));
        players.add(new AIPlayer("电脑1"));
        players.add(new AIPlayer("电脑2"));

        // 发牌
        dealCards();

        // 确定先出牌的玩家(持有黑桃3的玩家)
        determineFirstPlayer();

        lastPlayedCards = new ArrayList<>();
    }

    // 发牌
    private void dealCards() {
        int playerCount = players.size();
        for (int i = 0; i < deck.size(); i++) {
            players.get(i % playerCount).addCard(deck.get(i));
        }

        // 玩家手牌排序
        for (Player player : players) {
            player.sortCards();
        }
    }

    // 确定先出牌的玩家(持有黑桃3的玩家)
    private void determineFirstPlayer() {
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).hasCard("♠", "3")) {
                currentPlayerIndex = i;
                System.out.println(players.get(i).getName() + "拥有黑桃3，先出牌！");
                return;
            }
        }
        // 如果没有玩家有黑桃3(理论上不可能)，随机选择
        currentPlayerIndex = new Random().nextInt(players.size());
    }


    // 在ZhengShangYou类中添加连续不出牌计数器
    private int consecutivePasses = 0; // 记录连续不出牌的次数                    //修改了


    // 游戏主循环
    private void play() {
        Scanner scanner = new Scanner(System.in);

        while (true) {
            Player currentPlayer = players.get(currentPlayerIndex);

            // 显示游戏状态
            displayGameStatus(currentPlayer);

            // 玩家出牌
            List<Card> playedCards = currentPlayer.play(lastPlayedCards);

            if (playedCards == null) {
                // 玩家选择不出
                System.out.println(currentPlayer.getName() + "选择不出！");
                consecutivePasses++;                                            //修改了
                // 如果连续两个玩家不出牌，重置回合
                if (consecutivePasses >= 2) {                                   //修改了
                    System.out.println("连续两个玩家不出牌，本轮结束！");             //修改了
                    lastPlayedCards = new ArrayList<>(); // 清空上一手牌          //修改了
                    consecutivePasses = 0; // 重置计数器                         //修改了
                }
            } else {
                // 更新上一手牌
                lastPlayedCards = playedCards;
                System.out.println(currentPlayer.getName() + "出牌: " + formatCards(playedCards));
                consecutivePasses = 0; // 有人出牌时重置计数器                    //修改了

                // 从玩家手牌中移除已出的牌
                currentPlayer.removeCards(playedCards);

                // 检查玩家是否已出完牌
                if (currentPlayer.getCardCount() == 0) {
                    System.out.println(currentPlayer.getName() + "率先出完牌，获胜！");
                    break;
                }
            }

            // 轮到下一个玩家
            currentPlayerIndex = (currentPlayerIndex + 1) % players.size();
        }

        scanner.close();
    }

    // 显示游戏状态
    private void displayGameStatus(Player currentPlayer) {
        System.out.println("\n==============================");
        System.out.println("当前是" + currentPlayer.getName() + "的回合");

        // 显示上一手牌
        if (!lastPlayedCards.isEmpty()) {
            System.out.println("上一手牌: " + formatCards(lastPlayedCards));
        } else {
            System.out.println("新回合开始，请出牌");
        }

        // 如果是人类玩家，显示手牌
        if (currentPlayer instanceof HumanPlayer) {
            System.out.println("你的手牌: " + formatCards(currentPlayer.getCards()));
        }

        // 显示各玩家剩余牌数
        System.out.println("\n剩余牌数:");
        for (Player player : players) {
            System.out.println(player.getName() + ": " + player.getCardCount() + "张");
        }
    }

    // 格式化牌组显示
    private String formatCards(List<Card> cards) {
        return cards.stream().map(Card::toString).collect(Collectors.joining(" "));
    }

    // 卡牌类
    private static class Card implements Comparable<Card> {
        private String suit;
        private String rank;

        public Card(String suit, String rank) {
            this.suit = suit;
            this.rank = rank;
        }

        public String getSuit() {
            return suit;
        }

        public String getRank() {
            return rank;
        }

        // 获取牌的点数权重
        public int getWeight() {
            switch (rank) {
                case "3": return 3;
                case "4": return 4;
                case "5": return 5;
                case "6": return 6;
                case "7": return 7;
                case "8": return 8;
                case "9": return 9;
                case "10": return 10;
                case "J": return 11;
                case "Q": return 12;
                case "K": return 13;
                case "A": return 14;
                case "2": return 15;
                case "小王": return 16;
                case "大王": return 17;
                default: return 0;
            }
        }

        @Override
        public String toString() {
            return suit + rank;
        }

        @Override
        public int compareTo(Card other) {
            return Integer.compare(this.getWeight(), other.getWeight());
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            Card card = (Card) obj;
            return Objects.equals(suit, card.suit) && Objects.equals(rank, card.rank);
        }

        @Override
        public int hashCode() {
            return Objects.hash(suit, rank);
        }
    }

    // 玩家抽象类
    private abstract static class Player {
        protected String name;
        protected List<Card> cards;

        public Player(String name) {
            this.name = name;
            this.cards = new ArrayList<>();
        }

        public String getName() {
            return name;
        }

        public List<Card> getCards() {
            return cards;
        }

        public int getCardCount() {
            return cards.size();
        }

        public void addCard(Card card) {
            cards.add(card);
        }

        public void sortCards() {
            cards.sort(Comparator.naturalOrder());
        }

        public void removeCards(List<Card> cardsToRemove) {
            cards.removeAll(cardsToRemove);
        }

        public boolean hasCard(String suit, String rank) {
            return cards.contains(new Card(suit, rank));
        }

        public abstract List<Card> play(List<Card> lastPlayedCards);
    }

    // 人类玩家
    private static class HumanPlayer extends Player {
        private Scanner scanner;

        public HumanPlayer(String name) {
            super(name);
            scanner = new Scanner(System.in);
        }

        @Override
        public List<Card> play(List<Card> lastPlayedCards) {
            System.out.println("请输入要出的牌(用空格分隔，输入'pass'跳过):");
            String input = scanner.nextLine().trim();

            if (input.equalsIgnoreCase("pass")) {
                return null;
            }

            // 解析输入的牌
            List<Card> playedCards = parseInputCards(input);
            if (playedCards == null) {
                System.out.println("输入无效，请重新输入！");
                return play(lastPlayedCards);
            }

            // 检查玩家是否拥有这些牌
            if (!cards.containsAll(playedCards)) {
                System.out.println("你没有这些牌，请重新输入！");
                return play(lastPlayedCards);
            }

            // 检查牌型是否合法
            if (!isValidPlay(playedCards, lastPlayedCards)) {
                System.out.println("不合法的牌型，请重新输入！");
                return play(lastPlayedCards);
            }

            return playedCards;
        }

        // 解析输入的牌
        private List<Card> parseInputCards(String input) {
            String[] parts = input.split("\\s+");
            List<Card> playedCards = new ArrayList<>();

            for (String part : parts) {
                boolean matched = false;
                for (Card card : cards) {
                    if (card.toString().equals(part)) {
                        playedCards.add(card);
                        matched = true;
                        break;
                    }
                }
                if (!matched) {
                    return null;
                }
            }

            return playedCards;
        }
    }

    // AI玩家
    private static class AIPlayer extends Player {
        public AIPlayer(String name) {
            super(name);
        }

        @Override
        public List<Card> play(List<Card> lastPlayedCards) {
            // 简单的AI策略
            if (lastPlayedCards.isEmpty()) {
                // 如果是新回合，出最小的单张
                return Collections.singletonList(cards.get(0));
            }

            // 尝试出比上一手牌大的牌
            List<Card> possiblePlay = findPossiblePlay(lastPlayedCards);
            System.out.println( possiblePlay);
            // 如果没有合适的牌，选择不出
            return possiblePlay;
        }

        // 寻找可能的出牌
        private List<Card> findPossiblePlay(List<Card> lastPlayedCards) {
            int lastType = getCardType(lastPlayedCards);
            int lastWeight = getCardsWeight(lastPlayedCards);

            // 根据上一手牌型寻找合适的牌
            switch (lastType) {
                case SINGLE:
                    return findHigherSingle(lastWeight);
                case PAIR:
                    return findHigherPair(lastWeight);
                case TRIPLE:
                    return findHigherTriple(lastWeight);
                // 其他牌型处理类似...
                default:
                    return null;
            }
        }

        // 寻找更大的单张
        private List<Card> findHigherSingle(int lastWeight) {
            for (Card card : cards) {
                if (card.getWeight() > lastWeight) {
                    return Collections.singletonList(card);
                }
            }
            return null;
        }

        // 寻找更大的对子
        private List<Card> findHigherPair(int lastWeight) {
            Map<Integer, Integer> rankCount = new HashMap<>();
            for (Card card : cards) {
                int weight = card.getWeight();
                rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
            }

            for (Map.Entry<Integer, Integer> entry : rankCount.entrySet()) {
                if (entry.getValue() >= 2 && entry.getKey() > lastWeight) {
                    List<Card> pair = new ArrayList<>();
                    int count = 0;
                    for (Card card : cards) {
                        if (card.getWeight() == entry.getKey() && count < 2) {
                            pair.add(card);
                            count++;
                        }
                    }
                    return pair;
                }
            }
            return null;
        }

        // 寻找更大的三张
        private List<Card> findHigherTriple(int lastWeight) {
            Map<Integer, Integer> rankCount = new HashMap<>();
            for (Card card : cards) {
                int weight = card.getWeight();
                rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
            }

            for (Map.Entry<Integer, Integer> entry : rankCount.entrySet()) {
                if (entry.getValue() >= 3 && entry.getKey() > lastWeight) {
                    List<Card> triple = new ArrayList<>();
                    int count = 0;
                    for (Card card : cards) {
                        if (card.getWeight() == entry.getKey() && count < 3) {
                            triple.add(card);
                            count++;
                        }
                    }
                    return triple;
                }
            }
            return null;
        }
    }


    // 判断牌型是否合法
    private static boolean isValidPlay(List<Card> playedCards, List<Card> lastPlayedCards) {
        if (playedCards == null || playedCards.isEmpty()) {
            return false;
        }

        int currentType = getCardType(playedCards);
        if (currentType == -1) {
            return false; // 无效牌型
        }

        // 如果是新回合，任何合法牌型都可以
        if (lastPlayedCards == null || lastPlayedCards.isEmpty()) {
            return true;
        }

        int lastType = getCardType(lastPlayedCards);

        // 炸弹可以接任何牌
        if (currentType == BOMB || currentType == KING_BOMB) {
            return true;
        }

        // 牌型必须相同才能比较
        if (currentType != lastType) {
            return false;
        }

        // 比较牌的大小
        return getCardsWeight(playedCards) > getCardsWeight(lastPlayedCards);
    }



//四带二单四带二对                                                      //修改了471到496
    private static final int FOUR_WITH_TWO = 11;

    private static boolean isFourWithTwo(List<Card> cards) {
        int size = cards.size();
        if (size != 6) return false;

        // 统计点数数量
        Map<Integer, Integer> rankCount = new HashMap<>();
        for (Card card : cards) {
            int weight = card.getWeight();
            rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
        }

        // 需有一个四张，剩余两张为单牌（两个不同点数）或对子（一个点数两张）
        if (rankCount.size() != 2) return false;

        boolean hasFour = false;
        int otherCount = 0;
        for (int count : rankCount.values()) {
            if (count == 4) hasFour = true;
            else otherCount = count;
        }

        return hasFour && (otherCount == 2); // 剩余两张为单牌（两个1）或对子（一个2）
    }



    // 获取牌型
    private static int getCardType(List<Card> cards) {
        if (cards == null || cards.isEmpty()) {
            return -1;
        }

        int size = cards.size();

        // 王炸
        if (size == 2 && cards.get(0).getRank().equals("小王") && cards.get(1).getRank().equals("大王")) {
            return KING_BOMB;
        }

        // 单张
        if (size == 1) {
            return SINGLE;
        }

        // 对子
        if (size == 2 && cards.get(0).getWeight() == cards.get(1).getWeight()) {
            return PAIR;
        }

        // 三张
        if (size == 3 && cards.get(0).getWeight() == cards.get(1).getWeight()
                && cards.get(1).getWeight() == cards.get(2).getWeight()) {
            return TRIPLE;
        }

        // 炸弹(四张相同)
        if (size == 4 && cards.get(0).getWeight() == cards.get(1).getWeight()
                && cards.get(1).getWeight() == cards.get(2).getWeight()
                && cards.get(2).getWeight() == cards.get(3).getWeight()) {
            return BOMB;
        }


        // 顺子判断                                                //修改了538到722
        if (isStraight(cards)) {
            return STRAIGHT;
        }

        // 连对判断
        if (isStraightPair(cards)) {
            return STRAIGHT_PAIR;
        }

        // 飞机判断
        if (isAirplane(cards)) {
            return AIRPLANE;
        }

        // 3带1
        if (size == 4 && isThreeWithOne(cards)) {
            return THREE_WITH_ONE;
        }

        // 3带2
        if (size == 5 && isThreeWithTwo(cards)) {
            return THREE_WITH_TWO;
        }

        return -1; // 无效牌型
    }

    private static final int THREE_WITH_ONE = 9;  // 3带1
    private static final int THREE_WITH_TWO = 10; // 3带2

    // 判断是否为3带1
    private static boolean isThreeWithOne(List<Card> cards) {
        // 统计每个点数的牌的数量
        Map<Integer, Integer> rankCount = new HashMap<>();
        for (Card card : cards) {
            int weight = card.getWeight();
            rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
        }

        // 3带1需要有一个点数出现3次，另一个点数出现1次
        if (rankCount.size() != 2) {
            return false;
        }

        boolean hasThree = false;
        boolean hasOne = false;

        for (int count : rankCount.values()) {
            if (count == 3) {
                hasThree = true;
            } else if (count == 1) {
                hasOne = true;
            }
        }

        return hasThree && hasOne;
    }

    // 判断是否为3带2
    private static boolean isThreeWithTwo(List<Card> cards) {
        // 统计每个点数的牌的数量
        Map<Integer, Integer> rankCount = new HashMap<>();
        for (Card card : cards) {
            int weight = card.getWeight();
            rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
        }

        // 3带2需要有一个点数出现3次，另一个点数出现2次
        if (rankCount.size() != 2) {
            return false;
        }

        boolean hasThree = false;
        boolean hasTwo = false;

        for (int count : rankCount.values()) {
            if (count == 3) {
                hasThree = true;
            } else if (count == 2) {
                hasTwo = true;
            }
        }

        return hasThree && hasTwo;
    }

    // 判断是否为顺子
    private static boolean isStraight(List<Card> cards) {
        int size = cards.size();
        if (size < 5) {
            return false;
        }
        // 顺子不能包含大小王
        for (Card card : cards) {
            if (card.getRank().equals("小王") || card.getRank().equals("大王")) {
                return false;
            }
        }
        // 对牌按点数排序
        List<Card> sortedCards = new ArrayList<>(cards);
        sortedCards.sort(Comparator.naturalOrder());
        for (int i = 1; i < size; i++) {
            if (sortedCards.get(i).getWeight() != sortedCards.get(i - 1).getWeight() + 1) {
                return false;
            }
        }
        return true;
    }

    // 判断是否为连对
    private static boolean isStraightPair(List<Card> cards) {
        int size = cards.size();
        if (size < 6 || size % 2 != 0) {
            return false;
        }
        // 连对不能包含大小王
        for (Card card : cards) {
            if (card.getRank().equals("小王") || card.getRank().equals("大王")) {
                return false;
            }
        }
        // 统计每个点数的牌的数量
        Map<Integer, Integer> rankCount = new HashMap<>();
        for (Card card : cards) {
            int weight = card.getWeight();
            rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
        }
        // 找出所有对子
        List<Integer> pairs = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : rankCount.entrySet()) {
            if (entry.getValue() == 2) {
                pairs.add(entry.getKey());
            }
        }
        if (pairs.size() < 3) {
            return false;
        }
        // 对点数排序
        pairs.sort(Integer::compareTo);
        for (int i = 1; i < pairs.size(); i++) {
            if (pairs.get(i) != pairs.get(i - 1) + 1) {
                return false;
            }
        }
        return true;
    }

    // 判断是否为飞机
    private static boolean isAirplane(List<Card> cards) {
        int size = cards.size();
        if (size < 6 || size % 3 != 0) {
            return false;
        }
        // 飞机不能包含大小王
        for (Card card : cards) {
            if (card.getRank().equals("小王") || card.getRank().equals("大王")) {
                return false;
            }
        }
        // 统计每个点数的牌的数量
        Map<Integer, Integer> rankCount = new HashMap<>();
        for (Card card : cards) {
            int weight = card.getWeight();
            rankCount.put(weight, rankCount.getOrDefault(weight, 0) + 1);
        }
        // 找出所有三张牌
        List<Integer> triples = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : rankCount.entrySet()) {
            if (entry.getValue() == 3) {
                triples.add(entry.getKey());
            }
        }
        if (triples.size() < 2) {
            return false;
        }
        // 对点数排序
        triples.sort(Integer::compareTo);
        for (int i = 1; i < triples.size(); i++) {
            if (triples.get(i) != triples.get(i - 1) + 1) {
                return false;
            }
        }
        return true;
    }




    // 获取牌组的权重(用于比较大小)
    private static int getCardsWeight(List<Card> cards) {
        int type = getCardType(cards);
        if (type == -1) {
            return -1;
        }

        // 对于单张、对子、三张、炸弹等，权重就是牌的点数
        if (type == SINGLE || type == PAIR || type == TRIPLE || type == BOMB) {
            return cards.get(0).getWeight();
        }

        // 王炸是最大的
        if (type == KING_BOMB) {
            return 8000; // 王炸权重最高
        } else if (type == BOMB) {
            return 7000 + cards.get(0).getWeight(); // 四炸：7000 + 点数
        }
        // 顺子、连对、飞机的权重为最小牌的权重
        if (type == STRAIGHT || type == STRAIGHT_PAIR || type == AIRPLANE) {      //修改了741到745
            List<Card> sortedCards = new ArrayList<>(cards);
            sortedCards.sort(Comparator.naturalOrder());
            return sortedCards.get(0).getWeight();
        }

        // 其他牌型的权重计算...

        return -1;
    }




    protected List<Card> cards;                                     //修改了754到813
    // 寻找可能的出牌
    private List<Card> findPossiblePlay(List<Card> lastPlayedCards) {
        int lastType = getCardType(lastPlayedCards);
        int lastWeight = getCardsWeight(lastPlayedCards);

        // 根据上一手牌型寻找合适的牌
        switch (lastType) {
            case STRAIGHT:
                return findHigherStraight(lastWeight);
            case STRAIGHT_PAIR:
                return findHigherStraightPair(lastWeight);
            case AIRPLANE:
                return findHigherAirplane(lastWeight);
            default:
                return null;
        }
    }

    // 寻找更大的顺子
    private List<Card> findHigherStraight(int lastWeight) {
        // 这里简化为简单遍历，实际可以优化
        for (int start = 0; start < cards.size(); start++) {
            for (int end = start + 5; end <= cards.size(); end++) {
                List<Card> possibleStraight = new ArrayList<>(cards.subList(start, end));
                if (isStraight(possibleStraight) && getCardsWeight(possibleStraight) > lastWeight) {
                    return possibleStraight;
                }
            }
        }
        return null;
    }

    // 寻找更大的连对
    private List<Card> findHigherStraightPair(int lastWeight) {
        // 这里简化为简单遍历，实际可以优化
        for (int start = 0; start < cards.size(); start++) {
            for (int end = start + 6; end <= cards.size(); end += 2) {
                List<Card> possibleStraightPair = new ArrayList<>(cards.subList(start, end));
                if (isStraightPair(possibleStraightPair) && getCardsWeight(possibleStraightPair) > lastWeight) {
                    return possibleStraightPair;
                }
            }
        }
        return null;
    }

    // 寻找更大的飞机
    private List<Card> findHigherAirplane(int lastWeight) {
        // 这里简化为简单遍历，实际可以优化
        for (int start = 0; start < cards.size(); start++) {
            for (int end = start + 6; end <= cards.size(); end++) {
                List<Card> possibleAirplane = new ArrayList<>(cards.subList(start, end));
                if (isAirplane(possibleAirplane) && getCardsWeight(possibleAirplane) > lastWeight) {
                    return possibleAirplane;
                }
            }
        }
        return null;
    }
}